use crate::handlers::create_message_event;
use crate::helpers::{
    count_ttr, /*count_unread_posts,*/ create_ttr, wrap_url, /*Bot*/
    DatabaseConnection,
};
use anyhow::{anyhow, Result};
use log::info;
use matrix_sdk::ruma::events::room::message::RoomMessageEventContent;
use matrix_sdk::{room::Joined, ruma::events::room::message::OriginalSyncRoomMessageEvent, Client};
use serde::Deserialize;
use std::ops::Deref;
use uuid::Uuid;
pub async fn random(
    ev: OriginalSyncRoomMessageEvent,
    _text: String,
    room: Joined,
    _client: Client,
    db: DatabaseConnection,
) -> Result<()> {
    info!("finding random post");
    let matrix_id = ev.sender.to_string();
    let user_id = get_user_id(matrix_id, &db).await.unwrap();
    let user_post = get_random_userpost(user_id, &db).await?.unwrap();
    let post = get_post(user_post.post_id, &db).await?.unwrap();
    let mut answer = {
        let url_str = &user_post.original_url;
        if let Some(title) = post.title {
            wrap_url(url_str, &title)
        } else {
            url_str.to_string()
        }
    };
    let ttr = count_ttr(post.word_count);
    if let Some(ttr) = ttr {
        create_ttr(&mut answer, ttr)
    };

    let content = RoomMessageEventContent::text_markdown(answer);

    info!("sending random post");
    let response = room.send(content, None).await.unwrap();
    let event_id = response.event_id.to_string();
    create_message_event(user_post.id, &db, event_id)
        .await
        .unwrap();
    info!("sent");
    Ok(())
}
async fn get_random_userpost(
    user_id: Uuid,
    db: &DatabaseConnection,
) -> Result<Option<UserPostRandom>> {
    let rows = db
.lock()
.await
.deref()
.query("SELECT id, post_id, original_url, show_real_url, read, favorite FROM userposts WHERE (read = false) AND (user_id = $1) ORDER BY (random())   LIMIT 1", &[&user_id]).await?;
    if let Some(row) = rows.get(0) {
        Ok(Some(UserPostRandom {
            id: (row.get(0)),
            post_id: (row.get(1)),
            original_url: (row.get(2)),
            show_real_url: (row.get(3)),
            read: (row.get(4)),
            favorite: (row.get(5)),
        }))
    } else {
        Ok(None)
    }
}
async fn get_post(post_id: Uuid, db: &DatabaseConnection) -> Result<Option<PostRandom>> {
    let rows = db
        .lock()
        .await
        .deref()
        .query(
            "SELECT real_url, title, word_count FROM posts WHERE id = $1",
            &[&post_id],
        )
        .await?;
    if let Some(row) = rows.get(0) {
        Ok(Some(PostRandom {
            real_url: row.get(0),
            title: row.get(1),
            word_count: row.get(2),
        }))
    } else {
        Ok(None)
    }
}
async fn get_user_id(matrix_id: String, db: &DatabaseConnection) -> Result<Uuid> {
    let rows = db
        .lock()
        .await
        .deref()
        .query("SELECT id FROM users WHERE matrix_id = $1", &[&matrix_id])
        .await?;
    if let Some(row) = rows.get(0) {
        Ok(row.get(0))
    } else {
        Err(anyhow!("user_id get error"))
    }
}
#[derive(Debug, Deserialize)]
pub struct UserPostRandom {
    pub id: Uuid,
    pub post_id: Uuid,
    pub original_url: String,
    pub show_real_url: bool,
    pub read: bool,
    pub favorite: bool,
}
#[derive(Debug, Deserialize, Clone)]
pub struct PostRandom {
    pub real_url: String,
    title: Option<String>,
    word_count: Option<i64>,
}
// impl PostRandom{
//      fn title(&self) -> Option<String>{
//          self.title.map(|title|title.to_string())
//      }
//  }*/
// fn original_or_real(user: &UserRandom, post: &UserPostRandom) -> bool {
//     user.show_real_url || post.show_real_url
// }
